home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / doc.lha / doc.doc / autogen.doc < prev    next >
Text File  |  1992-09-25  |  37KB  |  1,097 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11. ___________________________________________________________________
  12.  
  13.  
  14.                                    Automatische Generierung
  15.                                    effizienter Compiler
  16.  
  17.                                    J. Grosch
  18.  
  19.  
  20. ___________________________________________________________________
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. ___________________________________________________________________
  51.                                    GESELLSCHAFT FUeR MATHEMATIK
  52.                                    UND DATENVERARBEITUNG MBH
  53.  
  54.                                    FORSCHUNGSSTELLE FUeR
  55.                                    PROGRAMMSTRUKTUREN
  56.                                    AN DER UNIVERSITAeT KARLSRUHE
  57. ___________________________________________________________________
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.                                    Project
  76.  
  77.                              Compiler Generation
  78.  
  79.          ___________________________________________________________
  80.  
  81.                 Automatische Generierung effizienter Compiler
  82.  
  83.  
  84.                                  Josef Grosch
  85.  
  86.  
  87.                                 Jan. 12, 1989
  88.  
  89.          ___________________________________________________________
  90.  
  91.  
  92.                                 Report No. 13
  93.  
  94.  
  95.                              Copyright c 1989 GMD
  96.  
  97.  
  98.             Gesellschaft fuer Mathematik und Datenverarbeitung mbH
  99.                 Forschungsstelle an der Universitaet Karlsruhe
  100.                           Vincenz-Priesznitz-Str. 1
  101.                                D-7500 Karlsruhe
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.                                                                              1
  135.  
  136.  
  137.                 Automatische Generierung effizienter Compiler
  138.  
  139.  
  140.                                  Josef Grosch
  141.   GMD Forschungsstelle fuer Programmstrukturen an der Universitaet Karlsruhe
  142.                 Vincenz-Priesznitz-Str. 1, D-7500 Karlsruhe 1
  143.  
  144.  
  145.  
  146. Zusammenfassung
  147.  
  148. Das Projekt UWE (Uebersetzerbau-Werkzeuge) zielt auf die Erstellung  von  Gen-
  149. eratorprogrammen, die es erlauben Compiler weitgehend automatisch zu erzeugen.
  150. Fuer die Analysephase von Compilern werden drei Generatoren  vorgestellt:  Rex
  151. ist  ein  Scanner-Generator  auf  der Basis regulaerer Ausdruecke. Der Parser-
  152. Generator Lalr erzeugt aus LALR(1)-Grammatiken tabellengesteuerte  Parser  mit
  153. S-Attributierung und automatischer Fehlerbehandlung.  Der Parser-Generator Ell
  154. erzeugt  aus  LL(1)-Grammatiken  Parser  nach  dem  Verfahren  des  rekursiven
  155. Abstiegs  mit  einem  Mechanismus  zur  L-Attributierung und ebenfalls automa-
  156. tischer Fehlerbehandlung.  Alle Generatoren sind in Modula-2 programmiert  und
  157. erzeugen  Programme  in  C  oder  Modula-2.  Die herausragende Eigenschaft der
  158. erzeugten Programme ist ihre Geschwindigkeit. Auf  einem  MC  68020  Prozessor
  159. erreichen  die Scanner bis zu 200.000 und die Parser um die 400.000 Zeilen pro
  160. Minute. Diese Geschwindigkeiten uebertreffen die UNIX Generatoren Lex und Yacc
  161. um die Faktoren 4 bzw. 2 bis 3.
  162.  
  163. Abstract
  164.  
  165. The project UWE (compiler construction tools) has the goal to implement a com-
  166. plete set of tools for the largely automatic construction of compilers.  Three
  167. tools for the analysis phase of compilers are presented: Rex is a scanner gen-
  168. erator  based  on  regular  expressions.   The parser generator Lalr generates
  169. table-driven parsers for LALR(1) grammars that  include  a  mechanism  for  S-
  170. attribution  and  automatic error reporting, recovery, and repair.  The parser
  171. generator Ell generates recursive descent parsers for LL(1)  grammars  with  a
  172. mechanism  for  L-attribution and an automatic error recovery similar to Lalr.
  173. All the tools are implemented in  Modula-2  and  generate  programs  in  C  or
  174. Modula-2.  The  outstanding property of the generated programs is their speed.
  175. On a MC 68020 processor the scanners reach  up  to  200,000  and  the  parsers
  176. around  400,000  lines per minute. These speeds represent in comparison to the
  177. UNIX tools Lex and Yacc a clear improvement by factors of 4 respectively 2  to
  178. 3.
  179.  
  180. Projekt-Ueberblick
  181.  
  182.      Das Projekt UWE (fuer  Uebersetzerbau-Werkzeuge)  befaszt  sich  mit  der
  183. Technik  des  Uebersetzerbaus  (Compiler-Baus), der Systematisierung der dabei
  184. verwendeten Methoden und Verfahren  sowie  deren  Umsetzung  in  Generatorpro-
  185. gramme.  Dies  schlieszt  die Entwicklung von Spezifikationstechniken fuer die
  186. verschiedenen Compiler-Teile ein. Das Ziel ist die Erstellung eines vollstaen-
  187. digen  Satzes  von  Werkzeugen oder Generatorprogrammen zur weitgehend automa-
  188. tischen Konstruktion von Compilern.  Dabei wird gegenueber einer Compiler-Ent-
  189. wicklung von Hand angestrebt, den Konstruktionsaufwand deutlich zu reduzieren,
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.                                                                              2
  201.  
  202.  
  203. die Fehlerfreiheit und Zuverlaessigkeit zu  steigern  und  eine  vergleichbare
  204. Effizienz bzw.  Uebersetzungsgeschwindigkeit zu erreichen.
  205.  
  206.      Die Beschaeftigung mit Uebersetzerbau-Werkzeugen geht auf  den  Lehrstuhl
  207. fuer  Uebersetzerbau an der Universitaet Karlsruhe zurueck, aus dem heraus die
  208. GMD Forschungsstelle Karlsruhe entstanden ist. Dort wurden bereits das  Parser
  209. Generating   System  PGS  (LALR(1)-Zerteiler-Generator),  der  Generator  fuer
  210. Attribut-Grammatiken GAG (semantische Analyse) und das Code Generator Synthese
  211. System CGSS (erzeugt Code-Generatoren aus Maschinenbeschreibungen) entwickelt.
  212. Diese Werkzeuge wurden an der GMD Forschungsstelle Karlsruhe  weiterentwickelt
  213. und  inzwischen weltweit an ueber 100 Institutionen weitergegeben. Diese quasi
  214. erste  Generation  von  Werkzeugen  erfuellte  bereits  die   Forderung   nach
  215. Steigerung  der Zuverlaessigkeit der erzeugten Compiler-Teile. Das kann man am
  216. erfolgreichen Einsatz  fuer  realistische  Anwendungen  sehen,  wie  etwa  dem
  217. Karlsruher  Ada  Compiler  oder  der  Norm  fuer  PEARL. Die im folgenden vor-
  218. gestellten Werkzeuge der zweiten Generation schlieszen die Luecke  im  Bereich
  219. der  lexikalischen Analyse und erzeugen fuer die Syntaxanalyse komfortable und
  220. effiziente Zerteiler.
  221.  
  222. Der Scanner-Generator Rex
  223.  
  224.      Der Scanner-Generator Rex wurde mit dem Ziel  entwickelt,  die  maechtige
  225. Spezifikationsmethode der regulaeren Ausdruecke mit der Generierung moeglichst
  226. effizienter Scanner zu kombinieren. Der Name Rex steht fuer regular expression
  227. tool und spiegelt die Spezifikationsmethode wider.  Eine Scanner-Spezifikation
  228. besteht im Prinzip aus einer Menge  regulaerer  Ausdruecke  wobei  jedem  eine
  229. semantische  Aktion zugeordnet ist. Diese Aktionen sind beliebige Anweisungen,
  230. die in einer der Zielsprachen C oder Modula-2 programmiert  sind.  Immer  wenn
  231. eine  Zeichenkette,  die  durch einen regulaeren Ausdruck beschrieben wird, in
  232. der Eingabe das Scanners erkannt wird, werden die Anweisungen der zugehoerigen
  233. Aktion  ausgefuehrt. Um Zeichenketten auch in Abhaengigkeit vom Kontext erken-
  234. nen zu koennen stehen sogenannte Startzustaende zur Behandlung von linkem Kon-
  235. text  zur  Verfuegung,  und  der rechte Kontext kann durch einen zusaetzlichen
  236. regulaeren Ausdruck spezifiziert werden. Sollten mehrere regulaere  Ausdruecke
  237. zu  einer  Eingabe  passen,  so  wird  derjenige  bevorzugt,  der die laengste
  238. Zeichenfolge erkennt. Falls immer noch mehrere Moeglichkeiten  bestehen,  wird
  239. davon der erste regulaere Ausdruck in der Spezifikation gewaehlt.
  240.  
  241.      Mit Rex erzeugte Scanner stellen automatisch fuer jede erkannte Zeichenk-
  242. ette die Zeilen- und Spalten-Position zur Verfuegung. Fuer Sprachen wie Pascal
  243. und Ada, wo Grosz- und Kleinbuchstaben nicht  unterschieden  werden,  gibt  es
  244. eine Normalisierung auf Grosz- oder Kleinbuchstaben. Vordefinierte Regeln ges-
  245. tatten das Ueberlesen unbedeutender Zeichen wie Leerzeichen, Tabulatoren  oder
  246. Zeilenwechsel.
  247.  
  248.      Die erzeugten Scanner sind tabellengesteuerte  deterministische  endliche
  249. Automaten.  Da  die  Tabellen duenn besetzte Matrizen sind, werden sie mit der
  250. sogenannten  "Kammvektor-Technik"   komprimiert.   Diese   kombiniert   grosze
  251. Speicherreduktion  mit  schnellem  Tabellenzugriff.  Der  Generator Rex ist in
  252. Modula-2 programmiert und kann zur Zeit Scanner in den Sprachen C und Modula-2
  253. erzeugen.   Rex  laeuft  inzwischen auf den Rechnern SUN/UNIX, PCS Cadmus/UNIX
  254. und VAX/BSD UNIX bzw. ULTRIX.
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.                                                                              3
  266.  
  267.  
  268.      Die herausragende  Eigenschaft  von  Rex  ist  die  Geschwindigkeit.  Die
  269. erzeugten  Scanner  verarbeiten  bis  zu  200.000  ohne und 150.000 Zeilen pro
  270. Minute mit Anwendung eines Hash-Verfahrens fuer Bezeichner. Dies ist die vier-
  271. fache  Geschwindigkeit  gegenueber  Scannern,  die  mit  dem UNIX-Werkzeug Lex
  272. [Les75] erzeugt wurden. In typischen Faellen haben die generierten Scanner nur
  273. ein  Viertel  der Groesze wie bei Lex (z. B. 11 KB fuer Modula-2). Gewoehnlich
  274. benoetigt Rex nur 1/10 der Zeit von Lex um  einen  Scanner  zu  erzeugen.  Die
  275. genannten Zahlen wurden auf einem MC 68020 Prozessor gemessen.
  276.  
  277. Scanner-Spezifikation mit Rechts-Kontext
  278.  
  279.      Die folgenden kleinen  Beispiele  zeigen  wie  Spezifikationen  fuer  Rex
  280. [Gro87]  aussehen.  Abbildung  1  spezifiziert  den  Aufbau ganzer und reeller
  281. Zahlen fuer die Sprache Modula-2. Die erste Zeile besagt, dasz eine ganze Zahl
  282. aus Folgen von Zeichen aus der Menge 0 bis 9 besteht. In Modula-2 gibt es, wie
  283. in manchen anderen Sprachen auch,  eine  Stelle,  an  der  die  Strategie  der
  284. laengsten  Zeichenkette  fehlschlaegt.  So  sollte etwa die Eingabe 1.. in die
  285. Zeichenketten "1" und "..", nicht aber in "1." und  "."  zerlegt  werden,  was
  286. alles legale Modula-2-Symbole waeren.
  287.  
  288.     {0-9} +             : { RETURN SymDecimal; }
  289.     {0-9} + / ".."      : { RETURN SymDecimal; }
  290.     {0-9} + "." {0-9} * (E {+\-} ? {0-9} +) ?
  291.                         : { RETURN SymReal   ; }
  292.     ".."                : { RETURN SymRange  ; }
  293.     "."                 : { RETURN SymDot    ; }
  294.  
  295.     Abbildung 1: Scanner-Spezifikation mit Rechts-Kontext
  296.  
  297.  
  298.      Das Problem kann mit einem zusaetzlichen regulaeren Ausdruck geloest wer-
  299. den.  Dieser  beschreibt  den  rechten  Kontext eines Symbols welches zu einer
  300. Ausnahme der Strategie der laengsten Zeichenkette fuehrt. In der zweiten Zeile
  301. trennt  das  Zeichen  '/'  zwei regulaere Ausdruecke und spezifiziert so, dasz
  302. eine Ziffernfolge erkannt werden soll, wenn zwei Punkte folgen.   Die  restli-
  303. chen  Zeilen  in  Abbildung  1 beschreiben die weiteren Symbole, die an diesem
  304. Problem beteiligt sind.
  305.  
  306. Scanner-Spezifikation mit Startzustaenden
  307.  
  308.      Manche Probleme lassen  sich  mit  regulaeren  Ausdruecken  allein  nicht
  309. loesen.  So erfordert etwa die Erkennung geschachtelter Kommentare in Modula-2
  310. einen zusaetzlichen Zaehler und den Einsatz von Startzustaenden (Abbildung 2).
  311. Der  Zaehler  wird  im Abschnitt GLOBAL deklariert und im Abschnitt BEGIN ini-
  312. tialisiert. Der Abschnitt START vereinbart einen Startzustand namens  Comment.
  313. Regeln,  vor  denen  ein  Startzustand  steht, sind nur wirksam, wenn sich der
  314. Scanner in diesem Startzustand befindet. Die  erste  Regel  erkennt  oeffnende
  315. Kommentarklammern, erhoeht den Schachtelungszaehler und schaltet in den Start-
  316. zustand Comment um. In letzterem sind alle 3 Regeln wirksam.  Entweder  werden
  317. Kommentarzeichen  ueberlesen  oder  bei  schlieszenden  Kommentarklammern  der
  318. Schachtelungszaehler erniedrigt. Erreicht dieser den Wert  Null,  so  ist  der
  319. Kommentar  zu  Ende, und es wird wieder in den vordefinierten Startzustand STD
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.                                                                              4
  331.  
  332.  
  333.  
  334.     GLOBAL  {VAR NestingLevel: CARDINAL;}
  335.     BEGIN   {NestingLevel := 0;}
  336.     EOF     {IF yyStartState = Comment THEN Error ("unclosed comment"); END;}
  337.     DEFINE  CmtCh   = - {*(0.
  338.     START   Comment
  339.     RULES
  340.                "(*" : {INC (NestingLevel); yyStart (Comment);}
  341.     #Comment#  "*)" : {DEC (NestingLevel);
  342.                        IF NestingLevel = 0 THEN yyStart (STD); END;}
  343.     #Comment#  "(" | "*" | CmtCh + : {}
  344.  
  345.     Abbildung 2: Scanner Spezifikation fuer geschachtelte Kommentare
  346.  
  347. zurueckgekehrt. Im Abschnitt EOF  stehen  Aktionen,  die  beim  Erreichen  des
  348. Eingabeendes auszufuehren sind. Hier wird im Falle einer fehlenden Kommentark-
  349. lammer ein entsprechender Fehler gemeldet.
  350.  
  351. Vergleich von Scanner-Generatoren
  352.  
  353.      Die Tabelle 1 vergleicht Rex mit dem UNIX Scanner-Generator Lex  und  dem
  354. Lex-Nachbau  Flex  (fuer  fast Lex). Die Tabelle vergleicht die Spezifikation-
  355. stechniken, die Werkzeuge und die  generierten  Scanner.  Die  spezifikations-
  356. abhaengigen  Zahlen wie Generierungszeit und Scanner-Groesze gelten fuer einen
  357. Modula-2-Scanner. Die Zahlen wurden auf einem MC 68020 Prozessor gemessen.
  358.  
  359. Der Parser-Generator Lalr
  360.  
  361.      Wie Rex wurde der Parser-Generator Lalr mit dem Ziel entwickelt eine mae-
  362. chtige  Spezifikationstechnik  fuer kontextfreie Grammatiken mit der Erzeugung
  363. effizienter Parser (Zerteiler) zu kombinieren. Der Name Lalr nimmt  Bezug  auf
  364. die Klasse der LALR(1)-Grammatiken, fuer die Zerteiler erzeugt werden koennen.
  365. Diese Grammatiken koennen in erweiterter BNF geschrieben  sein.  Jede  Gramma-
  366. tikregel  kann  mit semantischen Aktionen versehen werden, welche wiederum aus
  367. beliebigen Anweisungen der Zielsprache bestehen. Wenn der  erzeugte  Zerteiler
  368. eine Grammatikregel erkannt hat, werden die zugeordneten Aktionen ausgefuehrt.
  369. Es  steht  ein  Mechanismus  zur  S-Attributierung  zur  Verfuegung,   d.   h.
  370. abgeleitete Attribute koennen waehrend der Zerteilung berechnet werden.
  371.  
  372.      Gehoert eine Grammatik nicht zur LALR(1)-Klasse, so stellt der  Generator
  373. LR-Konflikte  fest.  Das Problem dabei besteht darin, fuer einen Konflikt aus-
  374. sagekraeftige Information zu liefern, um das Problem in der  Grammatik  finden
  375. zu  koennen und dann fuer Abhilfe zu sorgen. Waehrend andere Generatoren meist
  376. nur den Konflikt in Begriffen von internen Zustaenden und  Situationen  melden
  377. gibt   Lalr   Ableitungsbaeume   aus,   die  die  Konfliktbehebung  wesentlich
  378. erleichtern.  Syntaxfehler werden von den generierten  Zerteilern  vollautoma-
  379. tisch behandelt. Dies schlieszt Fehlermeldung, Wiederaufsetzen der Analyse und
  380. Fehlerreparatur ein. (Die genannten Eigenschaften  werden  unten  naeher  aus-
  381. gefuehrt.)
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.                                                                              5
  393.  
  394.  
  395.  
  396.                Tabelle 1: Vergleich einiger Scanner-Generatoren
  397.  
  398.  
  399. ____________________________________________________________________________________________
  400.                                   Lex                 Flex                Rex
  401. ____________________________________________________________________________________________
  402.  Spezifikationsmethode            regulaere           regulaere           regulaere
  403.                                     Ausdruecke          Ausdruecke          Ausdruecke
  404.  semantische Aktionen             ja                  ja                  ja
  405.  Rechts-Kontext                   ja                  ja                  ja
  406.  Links-Kontext (Startzustaende)   ja                  ja                  ja
  407. ____________________________________________________________________________________________
  408.  Konfliktloesung                  laengste Folge      laengste Folge      laengste Folge
  409.                                   erste Regel         erste Regel         erste Regel
  410. ____________________________________________________________________________________________
  411.  Quellposition                    Zeile               -                   Zeile + Spalte
  412.  Normalisierung                   -                   ja                  ja
  413.  vordefinierte Regeln zum         -                   -                   ja
  414.     Ueberlesen
  415.  mehrere Loesungen (REJECT)       ja                  ja                  -
  416.  Anpassung interner               von Hand            automatisch         automatisch
  417.     Datenstrukturen
  418. ____________________________________________________________________________________________
  419.  Scanneralgorithmus               tabellengesteuert   tabellengesteuert   tabellengesteuert
  420.  Tabellenkompression              Kammvektor          Kammvektor          Kammvektor
  421. ____________________________________________________________________________________________
  422.  Implementierungssprache          C                   C                   Modula-2
  423.  Zielsprachen                     C                   C                   C, Modula-2
  424. ____________________________________________________________________________________________
  425.  Geschwindigkeit [Zeilen/Min.]
  426.     ohne Hashing                  36.400              139.000             182.700
  427.     mit Hashing                   34.700              118.000             141.400
  428. ____________________________________________________________________________________________
  429.  Tabellengroesze [Bytes]          39.200              57.300              4.400
  430.  Scanner-Groesze [Bytes]          43.800              64.100              11.200
  431. ____________________________________________________________________________________________
  432.  Generierungszeit [Sek.]          73,7                7,2                 4,9
  433. ____________________________________________________________________________________________
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.                                
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.                                                                                            
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.      Die erzeugten Parser sind tabellengesteuert, wobei die  Tabellen  wie  im
  522. Fall von Rex mittels Kammvektor-Technik komprimiert werden. Der Generator Lalr
  523. ist in Modula-2 programmiert und kann zur Zeit Zerteiler  in  C  und  Modula-2
  524. erzeugen.  Wie  Rex  laeuft  Lalr  inzwischen  auf  den Rechnern SUN/UNIX, PCS
  525. Cadmus/UNIX und VAX/BSD UNIX bzw. ULTRIX.
  526.  
  527.      Mit Lalr erzeugte Zerteiler sind 2 bis 3 Mal schneller als mit  dem  UNIX
  528. Werkzeug  Yacc  [Joh75] generierte. Sie erreichen eine Geschwindigkeit von bis
  529. zu 400.000 Zeilen pro Minute auf einem MC 68020 Prozessor, wobei die Zeit fuer
  530. den  Scanner nicht beruecksichtigt ist. Von der Groesze her sind die Zerteiler
  531. im Vergleich zu Yacc etwas groeszer (z. B. 37 KB fuer Ada). Im folgenden  wer-
  532. den einige Eigenschaften von Lalr naeher vorgestellt.
  533.  
  534. S-Attributierung
  535.  
  536.      Die Spezifikation eines Zerteilers [GrV88] folgt dem Stil einer Rex Spez-
  537. ifikation.  Abbildung  3 zeigt ein einfaches Beispiel fuer einen Tischrechner,
  538.  
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.                                                                              6
  549.  
  550.  
  551. welcher arithmetische Ausdruecke akzeptiert, die aus den Operatoren  +  und  *
  552. sowie  Klammern  und  Zahlen aufgebaut sind.  Die in den geschweiften Klammern
  553. stehenden semantischen Aktionen sorgen fuer  die  Berechnung  der  Ausdruecke.
  554. Dazu  wird  dem  Nichtterminal expr und dem Terminal number das Attribut value
  555. zugeordnet. Mit $i  wird  in  den  semantischen  Aktionen  auf  die  Attribute
  556. zugegriffen.  Dabei bedeuten $i das i-te Grammatiksymbol der rechten Seite und
  557. $$ das Nichtterminal der linken Seite einer Regel.
  558.  
  559.     expr : expr '+' expr { $$.value := $1.value + $3.value; } .
  560.     expr : expr '*' expr { $$.value := $1.value * $3.value; } .
  561.     expr : '(' expr ')'  { $$.value := $2.value; } .
  562.     expr : number        { $$.value := $1.value; } .
  563.  
  564.     Abbildung 3: Grammatikregeln mit S-Attributierung
  565.  
  566.  
  567. Mehrdeutige Grammatiken
  568.  
  569.      Die Grammatik in Abbildung 3 und die Regeln in Abbildung 4 sind  typische
  570. Beispiele fuer mehrdeutige Grammatiken. Wie bei Yacc lassen sich daraus resul-
  571. tierende LR-Konflikte durch die Angabe von Prioritaet und Assoziativitaet fuer
  572. Terminale  (Operatoren)  loesen.   Abbildung  5 zeigt ein Beispiel. Die Zeilen
  573. stellen zunehmende  Prioritaeten  dar.  LEFT,  RIGHT  und  NONE  spezifizieren
  574. links-assoziative, rechts-assoziative bzw. Operatoren ohne Assoziativitaet.
  575.  
  576.     stmt : 'IF' expr 'THEN' stmt               PREC LOW
  577.          | 'IF' expr 'THEN' stmt 'ELSE' stmt   PREC HIGH .
  578.  
  579.     Abbildung 4: Mehrdeutige Grammatikregeln (Dangling Else Problem von Pascal)
  580.  
  581.  
  582.     OPER  LEFT '+'
  583.           LEFT '*'
  584.           NONE LOW
  585.           NONE HIGH
  586.  
  587.     Abbildung 5: Loesen von LR-Konflikten mit Prioritaet und Assoziativitaet
  588.  
  589.  
  590. Beschreibung von LR-Konflikten
  591.  
  592.      Zur leichteren Lokalisierung des Grundes fuer LR-Konflikte wurde eine von
  593. DeRemer  und  Pennello  [DeP82] vorgeschlagene Methode aufgegriffen. Neben der
  594. Art des  Konflikts  und  den  beteiligten  Situationen  wie  bei  anderen  LR-
  595. Generatoren  wird  zusaetzlich  ein Ableitungsbaum ausgegeben.  Eine Situation
  596. (item) ist eine Grammatikregel mit einem zusaetzlichen Punkt  in  der  rechten
  597. Seite,  welcher angibt, wie weit diese Regel bereits analysiert wurde.  Abbil-
  598. dung 6 zeigt ein Beispiel.
  599.  
  600.      Der Baum zeigt wie die Situationen und die Vorschauzeichen  in  den  Kon-
  601. fliktzustand  gelangen. Im allgemeinen wird fuer jede beteiligte Situation ein
  602. eigener Baum ausgegeben. Sind die Baeume jedoch gleich, wie das in Abbildung 6
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609.  
  610.  
  611.  
  612.  
  613.                                                                              7
  614.  
  615.  
  616.  
  617.     State 266
  618.     read reduce conflict
  619.     program End-of-Tokens
  620.     'PROGRAM' identifier params ';' block '.'
  621.     ................................:
  622.     :
  623.     labels consts types vars procs 'BEGIN' stmts 'END'
  624.     .......................................:
  625.     :
  626.     stmt
  627.     'IF' expr 'THEN' stmt 'ELSE' stmt
  628.                      :
  629.     reduce   stmt -> 'IF' expr 'THEN' stmt.  {'ELSE'}  ?
  630.     read     stmt -> 'IF' expr 'THEN' stmt.'ELSE' stmt  ?
  631.  
  632.     Abbildung 6: Ableitungsbaum fuer einen LR-Konflikt (Dangling Else Problem)
  633.  
  634. der Fall ist, so wird nur ein Baum ausgegeben.  Jeder Baum  besteht  aus  drei
  635. Teilen:  Ein  Anfangsteil  beginnt  mit  dem  Startsymbol. An einem bestimmten
  636. Knoten (Regel) erklaeren zwei weitere Teilbaeume die Entstehung der  Situation
  637. und der Vorschau.
  638.  
  639.      Jede Zeile enthaelt die rechte Seite einer Grammatikregel.  Normalerweise
  640. ist  diese  rechte  Seite so eingerueckt, dasz sie unter dem Nichtterminal der
  641. linken Seite beginnt. Um zu lange Zeilen zu  vermeiden,  verweisen  punktierte
  642. Linienzuege  ebenfalls  zum  Nichtterminal der linken Seite und erlauben so am
  643. linken Rand fortzufahren. In Abbildung 6 besteht der  Anfangsteil  des  Baumes
  644. aus  5 Zeilen, wobei die punktierten Zeilen nicht gezaehlt wurden. Die Symbole
  645. 'stmt' und 'ELSE' sind die  Wurzeln  der  beiden  weiteren  Teilbaeume.  Diese
  646. Stelle  ist mit einem "ueberfluessigen" Doppelpunkt gekennzeichnet. Nach einem
  647. Ableitungsschritt werden im linken Teilbaum die Konfliktsituationen  erreicht.
  648. Der  rechte Teilbaum besteht in diesem Fall nur aus dem Wurzelknoten (dem Sym-
  649. bol 'ELSE') und beschreibt das Vorschauzeichen. Im allgemeinen kann  hier  ein
  650. Baum  von  beliebiger Groesze stehen. Der LR-Konflikt kann in diesem Baumfrag-
  651. ment  leicht  abgelesen  werden.   Falls  bedingte  Anweisungen  wie   gezeigt
  652. geschachtelt werden liegt ein Lies-Reduziere-Konflikt vor.
  653.  
  654. Fehlerbehandlung
  655.  
  656.      Die generierten Zerteiler enthalten Information und Algorithmen  um  Syn-
  657. taxfehler  vollautomatisch  zu behandeln. Es wird die vollstaendige, rueckset-
  658. zungsfreie  Methode  von  Roehrich  [Roeh76,Roeh80,Roeh82]  verwendet.   Diese
  659. schlieszt  Fehlermeldungen, Wiederaufsetzen und Fehlerreparatur ein. Jede syn-
  660. taktisch fehlerhafte Eingabe wird gedachterweise  in  ein  korrektes  Programm
  661. transformiert.  Dies  bewirkt,  dasz  nur  korrekte  Folgen  von  semantischen
  662. Aktionen ausgefuehrt werden. Dadurch brauchen spaetere Compiler-Phasen wie die
  663. semantische  Analyse  auf  Syntaxfehler  keine Ruecksicht nehmen.  Lalr stellt
  664. einen Modul zur Sammlung oder Meldung von Fehlern zur Verfuegung,  der  leicht
  665. an  Benutzerwuensche  anpaszbar  ist. Ohne Modifikation werden Fehlermeldungen
  666. wie in Abbildung  7  ausgegeben.  Die  Fehlerbehandlung  laeuft  in  folgenden
  667. Schritten ab:
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.                                                                              8
  679.  
  680.  
  681.  
  682.     Quellprogramm:
  683.     program test (output);
  684.     begin
  685.        if (a = b] write (a);
  686.     end.
  687.     Fehlermeldungen:
  688.     3, 13: Error       syntax error
  689.     3, 13: Information expected symbols: ')' '*' '+' '-' '/' '<' '<='
  690.                        '=' '<>' '>' '>=' 'AND' 'DIV' 'IN' 'MOD' 'OR'
  691.     3, 15: Information restart point
  692.     3, 15: Repair      symbol inserted : ')'
  693.     3, 15: Repair      symbol inserted : 'THEN'
  694.  
  695.     Abbildung 7: Beispiel einer automatischen Fehlerbehandlung
  696.  
  697. - Die Position des Syntaxfehlers wird gemeldet.
  698.  
  699. - Alle Terminale, die eine korrekte Fortsetzung des Programms  waeren,  werden
  700.   berechnet und gemeldet.
  701.  
  702. - Alle Terminale, die zum Wiederaufsetzen der Zerteilung geeignet sind, werden
  703.   berechnet.  Eine  minimale  Folge  von Terminalen wird ueberlesen, bis eines
  704.   dieser Symbole gefunden wird.
  705.  
  706. - Die Position des Wiederaufsetzens wird gemeldet.
  707.  
  708. - Die Zerteilung wird im sogenannten  Reparaturmodus  fortgesetzt.  In  diesem
  709.   Modus  verhaelt sich der Zerteiler wie gewohnt ohne jedoch Terminale von der
  710.   Eingabe zu lesen. Stattdessen wird eine minimale Folge von  Terminalen  gen-
  711.   eriert, die gedachterweise die ueberlesenen Terminale ersetzt. Diese generi-
  712.   erten Terminale werden gemeldet. Der Zerteiler bleibt in diesem  Modus,  bis
  713.   das Terminal am Aufsetzpunkt akzeptiert werden kann. Danach wird der Repara-
  714.   turmodus verlassen und die Zerteilung normal fortgesetzt.
  715.  
  716. Der Parser-Generator Ell
  717.  
  718.      Der Parser-Generator Ell erzeugt aus LL(1)-Grammatiken Zerteiler nach dem
  719. Verfahren  des rekursiven Abstiegs. Die Grammatiken koennen in erweiterter BNF
  720. geschrieben sein und semantische Aktionen enthalten.  Innerhalb  der  Aktionen
  721. ist  es moeglich eine L-Attribut-Berechnung zu spezifizieren, die waehrend der
  722. Zerteilung ausgewertet wird. Es koennen sowohl erworbene als auch  abgeleitete
  723. Attribute  benutzt  werden,  solange  die  Auswertung  in  einem Links-Rechts-
  724. Durchlauf des Ableitungsbaums moeglich ist. Syntaxfehler werden wie  bei  Lalr
  725. vollautomatisch  behandelt  mit  Fehlermeldungen,  Wiederaufsetzen und Fehler-
  726. reparatur. Das Werkzeug ist ebenfalls in Modula-2 programmiert und  kann  Zer-
  727. teiler in C und Modula-2 erzeugen. Die Geschwindigkeit der erzeugten Zerteiler
  728. liegt im Augenblick bei 450.000 Zeilen pro Minute.  Zur Zeit wird  an  einigen
  729. Verbesserungen  gearbeitet,  wodurch  dieser  Wert  noch  steigen  wird.   Der
  730. Speicherbedarf liegt in der Groeszenordnung von tabellengesteuerten Zerteilern
  731. (z. B. 14 KB fuer Modula-2).
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742.                                                                              9
  743.  
  744.  
  745.  
  746.     ExpList : ( Expr ';'    { Write (Expr1.value, 10);                      }
  747.               ) *
  748.             .
  749.     Expr    : ( ['+'] Term  { Expr0.value := Term1.value;                   }
  750.               | '-' Term    { Expr0.value := - Term2.value;                 }
  751.               )
  752.               ( '+' Term    { INC (Expr0.value, Term3.value);               }
  753.               | '-' Term    { DEC (Expr0.value, Term4.value);               }
  754.               ) *
  755.             .
  756.     Term    : Factor        { Term0.value := Factor1.value;                 }
  757.               ( '*' Factor  { Term0.value := Term0.value * Factor2.value;   }
  758.               | '/' Factor  { Term0.value := Term0.value DIV Factor3.value; }
  759.               ) *
  760.             .
  761.     Factor  : Number        { Factor0.value := Number1;                     }
  762.             | '(' Expr ')'  { Factor0.value := Expr1.value;                 }
  763.             .
  764.  
  765.     Abbildung 8: LL(1)-Grammatik fuer einfachen Tischrechner
  766.  
  767.      Abbildung 8 zeigt die Spezifikation eines einfachen Tischrechners  mit  4
  768. Grundrechenarten  fuer  Ell.   Die  Spezifikation  erfolgt  durch  eine LL(1)-
  769. Grammatik in erweiterter BNF. Die  in  geschweifte  Klammern  eingeschlossenen
  770. semantischen Aktionen berechnen wiederum den Wert eines eingegebenen Ausdrucks
  771. und geben ihn aus. Der Zugriff auf Attribute erfolgt hier ueber die Namen  der
  772. Grammatiksymbole.  Da  mehrere  gleichnamige  Symbole in einer Regel vorkommen
  773. koennen werden zur Unterscheidung an die Namen Zahlen angehaengt. Die  Zahl  0
  774. bezeichnet  das  Nichtterminal  der linken Seite. Mit Zahlen groeszer 0 werden
  775. gleichnamige Symbole der rechten Seite von links nach rechts durchgezaehlt.
  776.  
  777. Vergleich von Parser-Generatoren
  778.  
  779.      Abschlieszend vergleicht die Tabelle 2 die  Parser-Generatoren  Lalr  und
  780. Ell  mit dem UNIX Werkzeug Yacc, mit dem Yacc-Nachbau Bison und mit PGS (siehe
  781. oben). Die Tabelle faszt die angesprochenen Eigenschaften zusammen und  sollte
  782. selbsterklaerend  sein.  Die  sprachabhaengigen  Zahlen sind ohne Laufzeit und
  783. Speicherbedarf fuer Scanner und beziehen sich auf Experimente mit einem Parser
  784. fuer Modula-2.
  785.  
  786. Zusammenfassung
  787.  
  788.      Die Uebersetzerbau-Werkzeuge Rex,  Lalr  und  Ell  wurden  mit  dem  Ziel
  789. entworfen,  maechtige  Spezifikationstechniken mit der automatischen Erzeugung
  790. effizienter Compiler-Teile zu kombinieren.  Es koennen Scanner und Parser in C
  791. und  Modula-2  erzeugt  werden,  die sich vor allem durch ihre Geschwindigkeit
  792. auszeichnen. Die Scanner verarbeiten  bis  zu  200.000  und  die  Parser  etwa
  793. 400.000  Zeile  pro  Minute  auf  einem MC 68020 Prozessor. Zusammen erreichen
  794. Scanner und Parser mehr als 100.000 Zeilen pro Minute oder  fast  2000  Zeilen
  795. pro Sekunde.
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.                                                                             10
  808.  
  809.  
  810.  
  811.                Tabelle 2: Vergleich einiger Parser-Generatoren
  812.  
  813.  
  814. ___________________________________________________________________________________________________
  815.                           Bison           Yacc            PGS          Lalr            Ell
  816. ___________________________________________________________________________________________________
  817.  Spezifikationsmethode    BNF             BNF             EBNF         EBNF            EBNF
  818.  Grammatikklasse          LALR(1)         LALR(1)         LALR(1)      LALR(1)         LL(1)
  819.                                                           LR(1)
  820.                                                           SLR(1)
  821.  semantische Aktionen     ja              ja              ja           ja              ja
  822.  S-Attributierung         numerisch       numerisch       symbolisch   numerisch       -
  823.  L-Attributierung         -               -               -            -               symbolisch
  824. ___________________________________________________________________________________________________
  825.  Konfliktmeldung          Zustand,        Zustand,        Zustand,     Ableitungs-     -
  826.                           Situation       Situation       Situation    baum
  827.  Konfliktloesung          Prioritaet      Prioritaet      Modifikation Prioritaet
  828.                           Assoziativitaet Assoziativitaet              Assoziativitaet
  829.  Kettenregelelimination   -               -               ja           -               -
  830.  Fehlerbehandlung         von Hand        von Hand        automatisch  automatisch     automatisch
  831.  Fehlerreparatur          -               -               ja           ja              ja
  832. ___________________________________________________________________________________________________
  833.  Zerteilungsverfahren     tabellen-       tabellen-       tabellen-    tabellen-       rekursiver
  834.                           gesteuert       gesteuert       gesteuert    gesteuert       Abstieg
  835.  Tabellenkompression      Kammvektor      Kammvektor      Kammvektor   Kammvektor      -
  836. ___________________________________________________________________________________________________
  837.  Implementgs.-Sprache     C               C               Pascal       Modula-2         Modula-2
  838.  Zielsprachen             C               C               C            C               C
  839.                                                           Modula-2     Modula-2        Modula-2
  840.                                                           Pascal
  841.                                                           Ada
  842. ___________________________________________________________________________________________________
  843.  Geschwindigkeit          105.000         184.000         200.000      385.000         437.000
  844.     [Zeilen/Min.]
  845. ___________________________________________________________________________________________________
  846.  Tabellengroesze [Bytes]  8.004           10.364          11.268       11.795          -
  847.  Zerteilergroesze [Bytes] 11.136          12.548          17.616       17.416          14.344
  848. ___________________________________________________________________________________________________
  849.  Generierungszeit [Sek.]  5,0             19,6            69,5         29,6            6,4
  850. ___________________________________________________________________________________________________
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.  
  880.  
  881.  
  882.                         
  883.  
  884.  
  885.  
  886.  
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.                                                                                                   
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.      Da erfahrungsgemaesz der Scanner einen Groszteil der  gesamten  Ueberset-
  948. zungszeit verbraucht, hoffen wir vollstaendige Compiler mit einer Geschwindig-
  949. keit von 1000 Zeilen pro Sekunde automatisch erzeugen zu koennen.   Im  Augen-
  950. blick  wird  an  der  Vervollstaendigung  des Werkzeugsatzes gearbeitet.  Dies
  951. betrifft Werkzeuge fuer die semantische Analyse auf der  Basis  attributierter
  952. Grammatiken,  Werkzeuge  fuer  die Transformation wie etwa die Erzeugung einer
  953. Zwischensprache und Werkzeuge fuer die Codeerzeugung auf der Basis von Muster-
  954. abgleich (pattern matching).
  955.  
  956.      Der Generator Lalr wurde von Bertram Vielsack programmiert, der auch  die
  957. experimentellen  Ergebnisse fuer den Vergleich der Parser-Generatoren beitrug.
  958. Der Generator Ell wurde von Doris Kuske programmiert.
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.                                                                             11
  972.  
  973.  
  974. Literatur
  975.  
  976. [DeP82]
  977.      F. DeRemer and T. Pennello, Efficient Computation of  LALR(1)  Look-Ahead
  978.      Sets, ACM Trans. Prog. Lang. and Systems 4, 4 (Oct. 1982), 615-649.
  979.  
  980. [Gro87]
  981.      J. Grosch, Rex - A Scanner Generator, Compiler Generation Report  No.  5,
  982.      GMD Forschungsstelle an der Universitat Karlsruhe, Dec. 1987.
  983.  
  984. [GrV88]
  985.      J. Grosch and B. Vielsack, The Parser Generators Lalr and  Ell,  Compiler
  986.      Generation   Report  No.  8,  GMD  Forschungsstelle  an  der  Universitat
  987.      Karlsruhe, Apr. 1988.
  988.  
  989. [Joh75]
  990.      S. C. Johnson, Yacc -  Yet Another  Compiler-Compiler,  Computer  Science
  991.      Technical  Report  32, Bell Telephone Laboratories, Murray Hill, NJ, July
  992.      1975.
  993.  
  994. [Les75]
  995.      M. E. Lesk,  LEX  -  A  Lexical  Analyzer  Generator,  Computing  Science
  996.      Technical Report 39, Bell Telephone Laboratories, Murray Hill, NJ, 1975.
  997.  
  998. [Roeh76]
  999.      J.  Rohrich,  Syntax-Error  Recovery  in   LR-Parsers,   in   Informatik-
  1000.      Fachberichte, vol. 1, H.-J. Schneider and M. Nagl (ed.), Springer Verlag,
  1001.      Berlin, 1976, 175-184.
  1002.  
  1003. [Roeh80]
  1004.      J. Rohrich, Methods for the Automatic Construction  of  Error  Correcting
  1005.      Parsers, Acta Inf. 13, 2 (1980), 115-139.
  1006.  
  1007. [Roeh82]
  1008.      J. Rohrich, Behandlung syntaktischer Fehler,  Informatik  Spektrum  5,  3
  1009.      (1982), 171-184.
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039. Inhalt
  1040.  
  1041.         Zusammenfassung .................................................    1
  1042.         Abstract ........................................................    1
  1043.         Projekt-Ueberblick ..............................................    1
  1044.         Der Scanner-Generator Rex .......................................    2
  1045.         Scanner-Spezifikation mit Rechts-Kontext ........................    3
  1046.         Scanner-Spezifikation mit Startzustaenden .......................    3
  1047.         Vergleich von Scanner-Generatoren ...............................    4
  1048.         Der Parser-Generator Lalr .......................................    4
  1049.         S-Attributierung ................................................    5
  1050.         Mehrdeutige Grammatiken .........................................    6
  1051.         Beschreibung von LR-Konflikten ..................................    6
  1052.         Fehlerbehandlung ................................................    7
  1053.         Der Parser-Generator Ell ........................................    8
  1054.         Vergleich von Parser-Generatoren ................................    9
  1055.         Zusammenfassung .................................................    9
  1056.         Literatur .......................................................   11
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.